package com.baidu.unlockdemo.customview

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.Rect
import android.graphics.RectF
import android.text.TextPaint
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
import android.view.MotionEvent
import android.view.View
import com.baidu.unlockdemo.R

/*
 自定义View
 1. 继承View
 2. 重写onMeasure方法 测量自己的尺寸
 */
class AnimationButton: View{
    //代码创建
    constructor(context: Context):super(context){}
    //xml创建
    constructor(context: Context, attrs: AttributeSet?):super(context,attrs){}

    /*
      确定自己的尺寸
      widthMeasureSpec： 父容器需要测量子控件的尺寸时，会携带宽度的测量标准过来
      heightMeasureSpec: 父容器需要测量子控件的尺寸时，会携带高度的测量标准过来
      32位数字组成：
        前两位： 表示父容器的测量标准
                match_parent         -> EXACTLY
                20dp                 -> EXACTLY
                match_constraint     -> EXACTLY
                wrap_content         -> AT_MOST
                                     -> Unspecified
                MeasureSpec.getMode(widthMeasureSpec)
        后30位： 具体的值
                MeasureSpec.getSize(widthMeasureSpec)
     */

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        val width_mode = MeasureSpec.getMode(widthMeasureSpec)
        val width_size = MeasureSpec.getSize(widthMeasureSpec)

        val height_mode = MeasureSpec.getMode(heightMeasureSpec)
        val height_size = MeasureSpec.getSize(heightMeasureSpec)

        var mWidth = 0
        var mHeight = 0
        when(width_mode){
            MeasureSpec.EXACTLY -> mWidth = width_size
            else -> mWidth = dp2px(300)
        }
        when(height_mode){
            MeasureSpec.EXACTLY -> mHeight = height_size
            else -> mHeight = dp2px(300)
        }

        //告诉父容器我的尺寸算好了
        setMeasuredDimension(mWidth,mHeight)
    }

    fun dp2px(dp: Int): Int = (dp * resources.displayMetrics.density + 0.5f).toInt()
    fun dp2pxf(dp: Int): Float = dp * resources.displayMetrics.density
    fun sp2pxf(sp: Int): Float = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_SP,
        sp.toFloat(),
        resources.displayMetrics
    )
    /**
     * onDraw方法会被多次调用
     * 所以不要在这个方法内部创建对象
     * Paint.ANTI_ALIAS_FLAG 抗锯齿 使得边缘平滑
     */
    private val mPaint:Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        //画笔的粗细
        this.strokeWidth = dp2pxf(15)
        //画笔的颜色
        this.color = Color.MAGENTA
        //画轮廓还是实心 Stroke 空心 FILL 实心
        this.style = Paint.Style.STROKE
        //端点的样式
        this.strokeCap = Paint.Cap.ROUND
        //连接点的样式
        this.strokeJoin = Paint.Join.ROUND
    }

    val mTextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
        this.textSize = sp2pxf(30)
        this.color = Color.MAGENTA
        this.bgColor = Color.WHITE
    }
    var rate = "0%"
    val mPath:Path = Path()
    val pathList = arrayListOf<Path>()
    override fun onDraw(canvas: Canvas) {
        //drawLine(canvas)
        //drawCircle(canvas)
        //drawRect(canvas)
        drawArcBackground(canvas)
        drawArc(canvas)
        drawText(canvas)
        //drawPath(canvas)

        //canvas.drawPath(mPath, mPaint)

    }


    /**
     * 这个方法会被多次调用
     * Android事件传递
     * Window -> DecorView -> Content(ConstraintLayout) ->LinearLayout -> AnimationButton
     * 如果父容器没有消费这个事件，子控件才有机会消费
     * return true 告诉系统事件在这里被消费了
     * MotionEvent: 封装了触摸事件
     *    getAction:
     *      ACTION_DOWN: 手指放在手机上那一刻触发这个down事件
     *      ACTION_MOVE: 在屏幕上移动
     *      ACTION_UP：   离开屏幕那一刻 触发up
     *      ACTION_CANCEL: 被系统应用打断 电话来了
     */
    var startX = 0f
    var startY = 0f
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        val action = event?.action
        when(action){
            MotionEvent.ACTION_DOWN ->{
                //手指按下
                startX = event.x
                startY = event.y
            }
            MotionEvent.ACTION_MOVE ->{
                //手指移动
                mPath.reset()

                mPath.moveTo(startX, startY)
                mPath.lineTo(event.x, event.y)
                //重新绘制
                //invalidate()
            }
            MotionEvent.ACTION_UP ->{
                //手指抬起
                //pathList.add(Path(mPath))
                mPath.reset()
                //invalidate()
            }
        }
        return true
    }

    private fun drawPath(canvas: Canvas){
        //路径的起点
        mPath.moveTo(measuredWidth/2f,measuredHeight/2f)
        mPath.lineTo(measuredWidth/4f,measuredHeight/2f)
        mPath.addCircle(measuredWidth/4f,measuredHeight/2f,dp2pxf(50),Path.Direction.CW)
        canvas.drawPath(mPath, mPaint)
    }

    private fun drawText(canvas: Canvas){
        //获取文本的metrics
        val metrics = mTextPaint.fontMetrics
        //获取文本的尺寸
        val textWidth = mTextPaint.measureText(rate)
        val cx = measuredWidth/2f-textWidth/2f
        val textHeight = metrics.descent-metrics.ascent

        //计算基准线到中心的距离
        /*
        val space = textHeight/2-metrics.bottom
        val cy = measuredHeight/2f+space
        */
        val cy = (measuredHeight+ textHeight)/2 - metrics.bottom
        canvas.drawText(rate,cx,cy,mTextPaint)
    }

    private var mSweepAngle = 0f
    fun setProgress(progress:Float){
        mSweepAngle = 360 * progress
        rate = "${(progress*100).toInt()}%"
        invalidate()
    }
    private fun drawArc(canvas: Canvas){
        mPaint.color = Color.MAGENTA
        //绘制弧形
        canvas.drawArc(
            dp2pxf(10),
            dp2pxf(10),
            measuredWidth.toFloat()- dp2pxf(10),
            measuredHeight.toFloat()-dp2pxf(10),
            270f,
            mSweepAngle,
            false,
            mPaint
        )
    }

    private fun drawArcBackground(canvas: Canvas){
        mPaint.color = Color.GRAY
        canvas.drawArc(
            dp2pxf(10),
            dp2pxf(10),
            measuredWidth.toFloat()- dp2pxf(10),
            measuredHeight.toFloat()-dp2pxf(10),
            0f,
            360f,
            false,
            mPaint
        )
    }

    private fun drawRect(canvas: Canvas){
        canvas.drawRect(
            dp2pxf(10)/2f,
            measuredHeight/2f,
            measuredWidth.toFloat()- dp2pxf(10)/2f,
            measuredHeight.toFloat()-dp2pxf(10)/2f,
            mPaint
        )
    }

    private fun drawCircle(canvas: Canvas){
        canvas.drawCircle(
            measuredWidth/2f,
            measuredHeight/2f,
            measuredWidth/2f-dp2pxf(10)/4f,
            mPaint
        )
    }

    private fun drawLine(canvas: Canvas){
        canvas.drawLine(
            0f,
            measuredHeight/2f,
            measuredWidth.toFloat(),
            measuredHeight/2f,
            mPaint
        )
    }
}